home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-10-25 | 5.1 KB | 137 lines | [TEXT/MPS ] |
- {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
- { UPatch.p }
- { Copyright © 1985-1990 by Apple Computer, Inc. All rights reserved. }
- {[f-]}
- {
- T H E O R Y O F O P E R A T I O N
-
- This unit implements a general trap-patching mechanism. Two types of
- patches are implemented:
-
- Normal Patch The trap is patched such that it jumps to the routine
- of your choice, ignoring the routine it previously
- jumped to. On a 128K ROM machine, the patch is made
- by setting the trap address to your routine. On a 64K
- machine, a small block of code is allocated in the
- system heap: The trap address is set to point to the
- block, and the block contains code to jump to your
- routine.
-
- Head Patch The trap is patched such that it jumps to the
- routine of your choice, then jumps to the trap's
- routine. Head patches come in two flavors: with
- no parameters and with one long-word parameter. The
- patch is made by allocating a small block of code in
- the application heap (system heap for 64K ROMs). The
- trap address is set to the block, and the block contains
- code to jump to your routine and return to the trap's
- original address.
-
- References to patches are kept in TrapPatch records. For each trap
- patched you must define a variable of type TrapPatch. This unit links
- the TrapPatch records to form a linked list for facilitate unpatching
- all patches without specifying each individual patch.
- }
- {[f+]}
-
- {$IFC UNDEFINED UsingIncludes}
- {$SETC UsingIncludes := FALSE}
- {$ENDC}
-
- {$IFC NOT UsingIncludes}
- UNIT UPatch;
-
- INTERFACE
- {$ENDC}
-
- {$IFC UNDEFINED __UPatch__}
- {$SETC __UPatch__ := FALSE}
- {$ENDC}
-
- {$IFC NOT __UPatch__}
- {$SETC __UPatch__ := TRUE}
-
- { • Auto-Include the requirements for this unit's interface. }
- {$SETC UPatchIncludes := UsingIncludes}
- {$SETC UsingIncludes := TRUE}
- {$I+}
- {$IFC UNDEFINED UsingTypes} {$I Types.p} {$ENDC}
- {$IFC UNDEFINED UsingMemory} {$I Memory.p} {$ENDC}
- {$SETC UsingIncludes := UPatchIncludes}
-
- TYPE
- TrapPatchPtr = ^TrapPatch; { Preferred. The pointer type _MUST_ be
- declared first since the record is self
- referential }
- TrapPatch = RECORD
- jmpPtr: Ptr; { Addr of sys heap block }
- trapNum: INTEGER; { trap # being patched }
- oldTrapAddr: LONGINT; { old trap address }
- nextPatch: TrapPatchPtr; { next link in linked list of patches }
- END;
-
- CallBack = RECORD
- saveRtnAdd: INTEGER; { Internal use }
- moveRefCon: INTEGER; { Internal use }
- refCon: LONGINT; { the refCon that will be passed as last
- parm }
- targOffset: INTEGER; { Internal use }
- jmpInst: INTEGER; { Internal use }
- jmpTarg: LONGINT; { Internal use }
- END;
- CallBackPtr = ^CallBack;
-
- { The following variable is really private but is in the interface just in case
- you're doing something really wierd and you really need it }
-
- VAR
- pPatchList: TrapPatchPtr; { Head of linked list of patches }
-
- PROCEDURE InitUPatch;
- { Call this once to set things up. Initializes the linked list of patches to NIL. }
-
- PROCEDURE EachPatchDo(FUNCTION DoToPatch(thePatchPtr: TrapPatchPtr): BOOLEAN);
- { Calls DoToPatch for each patch in the list from pPatchList to the last patch.
- Stops at end of list or when DoToPatch returns TRUE. DoToPatch may not remove patches. }
-
- FUNCTION HeadPatch(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): INTEGER;
- { HeadPatch patches a trap such that it calls theRoutine first, then executes the old trap
- routine. theRoutine must be a procedure with no arguments. This type of patch is
- implemented by setting up a block in the system heap, patching the trap to jump to the
- block, and inserting code in the block that pushes the original trap address on the stack
- and jumps to theRoutine. Thus, theRoutine returns to the original trap routine. }
-
- FUNCTION Head1Patch(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): INTEGER;
- { Head1Patch is just like HeadPatch, except that it is intended to patch traps with a single
- long-word parameter. The parameter passed to the trap is also passed to theRoutine.
- theRoutine must be a procedure with one long-word parameter. }
-
- FUNCTION PatchTrap(VAR thePatch: TrapPatch;
- theTrapNum: INTEGER;
- theRoutine: Ptr): INTEGER;
- { PatchTrap patches the given trap to theRoutine. On a 64K ROM machine, we must set up a
- block in the system heap, patch the trap to jump to the block, and insert code in the block
- to jump to theRoutine. }
-
- PROCEDURE SetCallBack(targProc: ProcPtr;
- itsRefCon: LONGINT;
- theCallBackPtr: CallBackPtr);
- { Prepares a call back record for use. Stuffs in the target of the call back and the refcon
- to pass as an _additional_ and _last_ parameter to it. Useful for getting context when being
- called back from the toolBox. Also useful for avoiding use of globals when getting context }
-
- PROCEDURE UnpatchTrap(VAR thePatch: TrapPatch);
- { UnpatchTrap unpatches the given trap. }
-
- PROCEDURE UnpatchAll;
- { UnpatchAll unpatches all traps. }
- {$ENDC}
-
- {$IFC NOT UsingIncludes}
- END.
- {$ENDC}
-